/*
@file: ast.cpp
@author: ZZH
@time: 2021-12-27 15:25:11
@info: 抽象语法树实现
*/
#include "ast.h"

ASTVariableDef_t::ASTVariableDef_t(const string& name, dataTypes::dataType_t type, uint32_t arrLen) :ASTNode_t(ASTNode_t::VariableDef)
{
    this->varName = name;
    this->varType = type;
    this->arrLen = arrLen;
    this->addr = 0;//默认无分配
}

bool ASTVariableDef_t::isSame(const ASTVariableDef_t& other) const
{
    bool res = true;
    // res &= this->varName == other.varName;
    res &= this->varType == other.varType;
    res &= this->arrLen == other.arrLen;
    return res;
}

//插入一个表达式
bool ASTBlockStatement_t::insert(ASTExpression_t* pExp)
{
    this->expList.push_back(pExp);
    return true;
}

ASTFunctionDef_t::ASTFunctionDef_t(const string& funcName, vArgSymTable_t* pVArgs, ASTBlockStatement_t* funcBody, dataTypes::dataType_t retType) :ASTNode_t(ASTNode_t::FunctionDef)
{
    this->funcName = funcName;
    this->pVArgs = pVArgs;
    this->funcBody = funcBody;
    this->retType = retType;
    this->addr = 0;//默认无分配
}

void ASTFunctionDef_t::check(const ASTFunctionDef_t* other) const
{
    bool isArgSizeDiff = (this->pVArgs == nullptr) && (other->pVArgs != nullptr);
    isArgSizeDiff |= (other->pVArgs == nullptr) && (this->pVArgs != nullptr);

    if (isArgSizeDiff)//此处用于处理某一方
        throw GrammarError("函数 %s 在声明与定义时给出的参数数量不一致", this->funcName.c_str());

    if (this->pVArgs->size() != other->pVArgs->size())
        throw GrammarError("函数 %s 在声明与定义时给出的参数数量不一致", this->funcName.c_str());

    for (auto pRef = this->pVArgs->begin(), pDef = other->pVArgs->begin(); pRef != this->pVArgs->end(); pRef++, pDef++)
    {
        if (not pRef->second->isSame(*pDef->second))
            throw GrammarError("函数 %s 在声明与定义时给出的参数类型不一致\r\n不一致的参数为: %s", this->funcName.c_str(), pRef->second->varName.c_str());
    }

    if (this->retType != other->retType)
        throw GrammarError("函数 %s 在声明与定义时给出的返回值类型不一致", this->funcName.c_str());
}

ASTOperatorDouble_t::ASTOperatorDouble_t(char op, ASTExpression_t* lexp, ASTExpression_t* rexp) :ASTExpression_t(ASTExpression_t::Eval)
{
    this->op = op;
    this->left_exp = lexp;
    this->right_exp = rexp;
}



